/**
 *@file
 *File contenente le funzioni per la gstione della partita in corso
 */ 

#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#include <iostream>
#include <fstream>
#include <allegro5/allegro_ttf.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_acodec.h>

using namespace std;

#include "struttura_dati.h"
#include "sn_main.h"
#include "gioco.h"

static double tempo=t_zero;/**<cambia la velocità del timer al crescere del punteggio*/





/**
 * Funzione privata invocata da ::genera_cibo a seguito dell'avvenuto incremento di punteggio
 * La funzione verifica che il punteggio sia un multiplo di 10,in caso affermativo
 * incrementa la velocità del timer mediante al_set_timer_speed
 *
 * @param[in] punti punteggio da verificare
 */  

void controlla_imposta_timer(int punti){

if(punti%10==0 && tempo>0.15){
	D1(cout<<"velocità timer prima di aumento : "<<tempo<<endl);
	tempo-=0.05;
	al_set_timer_speed(timer,tempo);
	D1(cout<<"velocità timer dopo aumento: "<<tempo<<endl);}
}


void cambia_direzione(ALLEGRO_EVENT_QUEUE *coda , ALLEGRO_EVENT &ev,direzione &direzione_s){
	
	switch(ev.keyboard.keycode) {
            
			case ALLEGRO_KEY_UP:
				if(direzione_s!=sotto)
					direzione_s=sopra;
					break;               
			
			case ALLEGRO_KEY_RIGHT:
				if(direzione_s!=sinistra)
					direzione_s=destra;
				break;
			
			case ALLEGRO_KEY_LEFT:
				if(direzione_s!=destra)
					direzione_s=sinistra;
				break;
		
			case ALLEGRO_KEY_DOWN:
				if(direzione_s!=sopra)
					direzione_s=sotto;
				break;
			
			case ALLEGRO_KEY_P:
				do{
					al_wait_for_event(coda, &ev);
					D2(cout<<"attendo input tastiera\n");}
				while(ev.type != ALLEGRO_EVENT_KEY_DOWN);
				break;
			
			default: return;
	}
			   	
}


/**
 * Genera le nuove coordinate x e y pseudocasuali per il cibo.
 * Funzione privata Invocata da ::cambia_posizione
 * Verifica dopo aver generato le coordinate che non coincidano con nessuno
 * degli elementi del vettore snake. In caso affermativo ne genera di nuove
 * altrimenti invoca la funzione ::controlla_imposta_timer
 * 
 * @param[in] snake[] vettore contenente le coordinate di ciascun elemento di snake  
 * @param[in] cibo variabile di tipo ::caratteristiche contenente le coordinate del cibo
 * @param[in] punti punteggio  
 */ 
void genera_cibo(caratteristiche snake[], caratteristiche &cibo, int punti){
	int i;	
	do{
		cibo.pos_x=rand()%dim_mappa;	
		cibo.pos_y=rand()%dim_mappa;
		assert(cibo.pos_x>=0 && cibo.pos_x<dim_mappa);
		assert(cibo.pos_y>=0 && cibo.pos_y<dim_mappa);
		D1(cout<<"cibo.pos_x: "<<cibo.pos_x<<"  "<<"cibo.pos_y: "<<cibo.pos_y<<endl;
		  cout<<"snake[0].pos_x: "<<snake[0].pos_x<<"  "<<"snake[0].pos_y: "<<snake[0].pos_y<<endl); 	
				
		for(i=0;i<=punti;i++){
			if(cibo.pos_x==snake[i].pos_x && cibo.pos_y==snake[i].pos_y) /*verifico che la posizione non sia gia occupata da snake*/
				break;}
	  }
	  while(i<=punti);	/*perche se sono uscito dal ciclo prima della sua fine vuol dire che la posizione era occupata*/
	assert(i>punti && punti>=0);
	controlla_imposta_timer(punti);
}



bool cambia_posizione(caratteristiche snake[],direzione dir,int & punti,caratteristiche & cibo){
	caratteristiche vecchia_pos, app; /*app è una variabile d'appoggio che mi serve per lo scambio dalla vecchia pos alla nuova*/
	vecchia_pos.pos_x=snake[0].pos_x; vecchia_pos.pos_y=snake[0].pos_y; //salva le coordinate della testa in una variabile	
	
	switch(dir){	
		
		case destra:
		
		if(++snake[0].pos_x>=dim_mappa) /*incremento la posizione della testa (coord_x) e verifico che non sia il muro*/
			return false;		
		break;	
						
		case sinistra:
		
		if(--snake[0].pos_x<0)  /*può assumere posizioni che vanno da 0 a dim_mappa-1*/ 
			return false;
		break;
		
		case sopra:
		
		if(--snake[0].pos_y<0)
			return false;
		break;
		
		case sotto:
		
		if(++snake[0].pos_y>=dim_mappa)
			return false;		
		}
	
	
	/* se sono arrivato qui vuol dire che non tocco le pareti*/
	
	/* verifico se tocco il corpo stesso*/
	int i = punti%2==0 ? punti-1 : punti;
	for(;i>=3; i-=2){
		if(snake[0].pos_x==snake[i].pos_x && snake[0].pos_y==snake[i].pos_y)
			return false;}
	
	
	/*aggiorno la posizione di ciascun elemento di snake*/
	for(int j=1;j<=punti;j++){
		app.pos_x=snake[j].pos_x;
		app.pos_y=snake[j].pos_y;
		snake[j].pos_x=vecchia_pos.pos_x;
		snake[j].pos_y=vecchia_pos.pos_y;
		vecchia_pos.pos_x=app.pos_x;  
		vecchia_pos.pos_y=app.pos_y;
		}
	/*verifico se ho colpito il cibo, cioè se le coordinate di snake[0]
	 *coincidono cono quelle di cibo, in tal caso incremento il punteggio
	 *assegno la posizione al nuovo elemento e negenero una nuova per il cibo*/
	if(snake[0].pos_x==cibo.pos_x && snake[0].pos_y==cibo.pos_y){
		punti++;
		al_play_sample(preso_cibo, 1.2, 0.0,1.0,ALLEGRO_PLAYMODE_ONCE,NULL);		
		snake[punti].pos_x=vecchia_pos.pos_x;
		snake[punti].pos_y=vecchia_pos.pos_y;	
		genera_cibo(snake,cibo, punti);}
		
return true;
	
}

void resetta_snake(caratteristiche snake[],int & punteggio, direzione & direzione_s,caratteristiche &cibo){
	punteggio=0;
	snake[0].pos_x= dim_mappa/2;
	snake[0].pos_y= dim_mappa/2;
	direzione_s=destra;
	tempo=t_zero;
	genera_cibo(snake, cibo,punteggio);
}			


		
void disegna_gioco(caratteristiche cibo, const caratteristiche snake[],direzione direzione_s, int punteggio){
	
	/*disegno cornice di gioco*/
	al_draw_bitmap(pareti, 0, 0, 0);  //la funzione ha ritorno void

	/*disegno immagine del cibo*/
	al_draw_bitmap(img_cibo,zero_map+cibo.pos_x*dim_object,zero_map+cibo.pos_y*dim_object,0);

	/*disegno testa del serpente ruotata al variare della direzione:
 	 *la funzione prende in ingresso: l'img; la coord x del centro;la coord y del centro;
 	 * le coord x e y di destinazione;l'angolo di rotazione e i flags.
 	 */
	al_draw_rotated_bitmap(head,25/2,25/2,zero_map+snake[0].pos_x*dim_object+dim_object/2,
					   zero_map+snake[0].pos_y*dim_object+dim_object/2,direzione_s*pi/2,0);
	/*disegno il corpo*/																							   
	for(int i=1;i<=punteggio;i++)
		al_draw_bitmap(body,zero_map+snake[i].pos_x*dim_object,zero_map+snake[i].pos_y*dim_object,0);

   
	/*disegno il punteggio*/	
	al_draw_text(ysel,al_map_rgb(255,127,50),700,60,ALLEGRO_ALIGN_CENTRE,"Score");
	al_draw_textf(ysel,al_map_rgb(255,127,50),700,130,ALLEGRO_ALIGN_CENTRE,"%i",punteggio);
	/*disegno logo*/
	al_draw_scaled_bitmap(logo,0,0,600,600,615,250,180,180,0);
	/*pausa*/	
	al_draw_text(nsel,al_map_rgb(255,127,50),705,490,ALLEGRO_ALIGN_CENTRE,"(P)ause");
}
	



